

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "support.h"
#include "codeview.h"
#include "window.h"
#include "statusbar.h"
#include "page_state.h"
#include "dialog.h"
#include "fileops.h"
#include "keypad.h"

/*######################## Globals ########################*/
GtkWidget *save_file_dialog;
GtkWidget *open_file_dialog;
GtkWidget *save_as_file_dialog;
GtkWidget *save_text_file_dialog;
GtkFileFilter *filter_sim;
gchar *ext=".sim";
gint if_close_file,if_file_processing; /*used by te close_unsaved dialog*/

/*######################## Static functions #################*/
//static void close_file_selection(GtkWidget *widget , gpointer data);
//static gboolean delete_file_selection(GtkWidget *widget , GdkEvent *event, gpointer data);
static void _save_file(void);
static void save_file_dialog_ok(void);
static void _open_file(void);
static void set_name_with_ext(const gchar *name_of_file);
static void save_as_file_dialog_ok(void);
static void save_text_file_dialog_ok(void);
static void _save_text_file(FILE *file);

/*############### if there any contents in the file ################*/
gboolean if_have_iter(void)
{
	if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(codeview_notebook))==0)
		return FALSE;
	if(!gtk_tree_model_get_iter_first(current_code_model,&current_code_iter))
		return FALSE;
	return TRUE;
}

/*######################### Create a new file #########################*/
void gsim_new_file(void)
{
	gsim_make_codeview_child(codeview_new_label());
	gtk_widget_show_all(codeview_notebook);
	gtk_notebook_set_current_page(GTK_NOTEBOOK( codeview_notebook ) ,0);
	new_file=1;
	if_new_file=1;
}

/*################## Close the all files ################*/
void close_file()
{
	gint n;
	n=gtk_notebook_get_current_page(GTK_NOTEBOOK(codeview_notebook));
	gtk_notebook_remove_page(GTK_NOTEBOOK(codeview_notebook),n);
	
	/*no more pages active set last tab to its initial state*/
	if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(codeview_notebook))==0)
	{
		last_page_label=NULL;
		current_code_model=NULL;
		gsim_update_statusbar(FILE_SBAR,_("No File"));
		gsim_init_keypad_state();
	}
	return;
}

	
void gsim_close_file(void)
{	
	if(save_state)
		gsim_close_unsaved();
	else
		close_file();
	return;
}


/*######################## Close all the files ######################*/
void gsim_close_all_files(void)
{
	gint n,i;
	n=gtk_notebook_get_n_pages(GTK_NOTEBOOK(codeview_notebook));
	for(i=0;i<n;i++)
	{
		gsim_close_file();
		while(if_file_processing)
			while(gtk_events_pending())
				gtk_main_iteration();
	}
	return;
}

/*####################### Hide the file selection ############*/
/*static void close_file_selection(GtkWidget *widget , gpointer data)
{
	gtk_widget_hide(GTK_WIDGET(data));
	if_file_processing=0;
}*/

/*####################### clicked x button  ############*/
/*static gboolean delete_file_selection(GtkWidget *widget , GdkEvent *event, gpointer data)
{
	gtk_widget_hide(widget);
	if_file_processing=0;
	return TRUE;
}*/

/*####################### Save the file ######################*/
static void set_name_with_ext(const gchar *name)
{
	gchar *x,*abs;
	x=strpbrk(name,".");
	if(!x) /*no extension*/
	{
		g_strlcpy(filename,g_path_get_basename(name),50);
		g_strlcat(filename,ext,50);/*update name*/
		GString *str;
		str=g_string_new("");
		g_string_append_printf(str,"%s%s",name,ext);             
		abs=g_malloc(str->len+1);
		g_strlcpy(abs,str->str,str->len+1);
		absolute_filename=abs;		/*update absolute filename*/
		g_string_free(str,TRUE);
	}
	else
	{
		g_strlcpy(filename,g_path_get_basename(name),50); /*update name*/
		absolute_filename=(gchar *)name;                    /*update absolute filename*/
	}
	
	/*update the lable of tab*/
	GList *child;
	GtkWidget *label;
	child=gtk_container_get_children(GTK_CONTAINER(last_page_label));
	label=g_list_nth_data(child,0);
	gtk_label_set_text(GTK_LABEL(label),filename);
	save_state=1;
	
}

static void _save_file(void)
{
	if(!save_state)
		return;
	struct gsim_signature sign={0x55,0xaa};
	
	FILE *file;
	file=fopen(absolute_filename,"wb");
	if(!file)
	{
		g_printerr(_("Unable to open %s : ERROR : %s\n"),filename,strerror(errno));
		return;
	}
	
	fwrite(&sign,sizeof(struct gsim_signature),1,file); /*write signature*/
	
	/*write the actual data*/
	GString *str;
	str=g_string_new(NULL);
	
	GtkTreeIter iter;
	gboolean if_iter;
	gint x;
	for(if_iter=gtk_tree_model_get_iter_first(current_code_model,&iter);if_iter;
											if_iter=gtk_tree_model_iter_next(current_code_model,&iter))
	{
		gchar *address,*label,*mne,*op1,*op2,*comment;
		gtk_tree_model_get(current_code_model,&iter,ADDR_COL,&address,LABEL_COL,&label,MNE_COL,&mne,
										OP1_COL,&op1,OP2_COL,&op2,COMMT_COL,&comment,-1);
		if(!mne)
			mne=g_strdup("x");       /*if a empty line(there is null mne so set it to x)*/
		
		g_string_truncate(str,0);   /*empty the string*/
		g_string_append_printf(str,":%s :%s :%s :%s :%s :%s",address,label,mne,op1,op2,comment); 
		x=str->len+1;
		fwrite(&x,sizeof(x),1,file);
		fwrite(str->str,x,1,file);
		
		g_free(address);
		g_free(label);
		g_free(mne);
		g_free(op1);
		g_free(op2);
		g_free(comment);
	}
	
	g_string_free(str,TRUE);
	save_state=0;                 
	new_file=0;                   /*no longer a new file*/
	if_new_file=0;
	gsim_update_statusbar(FILE_SBAR,filename);
	fclose(file);
}

static void save_file_dialog_ok(void)
{
	const gchar *_name;
	
	//_name=gtk_file_selection_get_filename(GTK_FILE_SELECTION(save_file_dialog));
	_name=gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (save_file_dialog));
	if(g_file_test(_name,G_FILE_TEST_IS_DIR|G_FILE_TEST_IS_SYMLINK)||*_name=='\0') /*if not a file*/
		return;
	
	set_name_with_ext(_name);
	_save_file();
	gtk_widget_hide(save_file_dialog);                   /*hide selection dialog*/
	
	/*if file to be closed after saving*/
	if(if_close_file)
	{
		if_close_file=0;
		close_file();
	}
	
	if_file_processing=0; /*file processing over*/
}

void gsim_save_file(void)
{
	/*check file is not empty*/
	if(!if_have_iter())
		return;
	if(!save_file_dialog) /*if it is first time*/
	{
		/*save_file_dialog=gtk_file_selection_new(_("Save File ..."));
		g_signal_connect(GTK_FILE_SELECTION(save_file_dialog)->ok_button,"clicked",G_CALLBACK(save_file_dialog_ok),NULL);
		g_signal_connect(GTK_FILE_SELECTION(save_file_dialog)->cancel_button,"clicked",G_CALLBACK(close_file_selection),save_file_dialog);
		g_signal_connect(save_file_dialog,"delete-event",G_CALLBACK(delete_file_selection),NULL);*/
		
		save_file_dialog = gtk_file_chooser_dialog_new ("Save File ...",
				      GTK_WINDOW(gsim_appwindow),
				      GTK_FILE_CHOOSER_ACTION_SAVE,
				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
				      NULL);
		gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (save_file_dialog), TRUE);
	}
	
	if(if_new_file)   /*if it is newfile(no name assigned)*/
	{
		if (gtk_dialog_run (GTK_DIALOG(save_file_dialog)) == GTK_RESPONSE_ACCEPT)
  		{
    		save_file_dialog_ok();
    	}

		gtk_widget_hide (save_file_dialog);
	}
	else
		_save_file();
	
}

/*####################### Save all file ####################*/
void gsim_save_all_files(void)
{
	gint n,i,x;
	n=gtk_notebook_get_n_pages(GTK_NOTEBOOK(codeview_notebook));
	x=gtk_notebook_get_current_page(GTK_NOTEBOOK(codeview_notebook));
	for(i=0;i<n;i++)
	{
		gtk_notebook_set_current_page(GTK_NOTEBOOK( codeview_notebook ) ,i);
		while(gtk_events_pending())
				gtk_main_iteration();
		
		if_file_processing=1;
		gsim_save_file();
		while(if_file_processing)
			while(gtk_events_pending())
				gtk_main_iteration();
	}
	gtk_notebook_set_current_page(GTK_NOTEBOOK( codeview_notebook ) ,x);
	return;
}

/*####################### Save file as #####################*/
static void save_as_file_dialog_ok(void)
{
	const gchar *_name;
	
	//_name=gtk_file_selection_get_filename(GTK_FILE_SELECTION(save_as_file_dialog));
    _name=gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (save_as_file_dialog));
	
	if(g_file_test(_name,G_FILE_TEST_IS_DIR|G_FILE_TEST_IS_SYMLINK)||*_name=='\0') /*if not a file*/
		return;
	
	set_name_with_ext(_name);
	_save_file();
	gtk_widget_hide(save_as_file_dialog);                   /*hide selection dialog*/
}

void gsim_save_as_file(void)
{
	/*check file is not empty*/
	if(!if_have_iter())
		return;
	if(!save_as_file_dialog) /*if it is first time*/
	{
		/*save_as_file_dialog=gtk_file_selection_new(_("Save File As ..."));
		g_signal_connect(GTK_FILE_SELECTION(save_as_file_dialog)->ok_button,"clicked",G_CALLBACK(save_as_file_dialog_ok),NULL);
		g_signal_connect(GTK_FILE_SELECTION(save_as_file_dialog)->cancel_button,"clicked",G_CALLBACK(close_file_selection),save_as_file_dialog);
		g_signal_connect(save_as_file_dialog,"delete-event",G_CALLBACK(delete_file_selection),NULL);*/
		
		save_as_file_dialog = gtk_file_chooser_dialog_new ("Save File As ...",
				      GTK_WINDOW(gsim_appwindow),
				      GTK_FILE_CHOOSER_ACTION_SAVE,
				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
				      NULL);
		gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (save_as_file_dialog), TRUE);
	}
	
	if (gtk_dialog_run (GTK_DIALOG (save_as_file_dialog)) == GTK_RESPONSE_ACCEPT)
  	{
    	save_as_file_dialog_ok();
    }

	gtk_widget_hide (save_as_file_dialog);
}

/*####################### Save the file ######################*/
static void _open_file(void)
{
	struct gsim_signature sign;
	FILE *file;
	file=fopen(absolute_filename,"rb");
	if(!file)
	{
		g_printerr(_("Unable to open %s : ERROR : %s\n"),filename,strerror(errno));
		return;
	}
	
	/*read sign*/
	fread(&sign,sizeof(struct gsim_signature),1,file); 
	
	/*read the actual data*/
	GString *str;
	str=g_string_new(NULL);
	
	gint x;
	while(fread(&x,sizeof(x),1,file))
	{
		gchar address[5],label[9],mne[5],op1[9],op2[5],*comment;

		g_string_set_size(str,x);
		fread(str->str,x,1,file);
		str->len=x-1;
		sscanf(str->str,"%s %s %s %s %s ",address,label,mne,op1,op2);
		comment=g_utf8_strrchr(str->str,str->len,':');
		comment++;

		gtk_tree_store_append(GTK_TREE_STORE(current_code_model),&current_code_iter,NULL);
		if(*(mne+2)=='\0') /*if a empty line*/
			gtk_tree_store_set(GTK_TREE_STORE(current_code_model),&current_code_iter,ADDR_COL,&address[1],LABEL_COL,&label[1],
									OP1_COL,&op1[1],OP2_COL,&op2[1],COMMT_COL,comment,-1);
		else
			gtk_tree_store_set(GTK_TREE_STORE(current_code_model),&current_code_iter,ADDR_COL,&address[1],LABEL_COL,&label[1],
									MNE_COL,&mne[1],OP1_COL,&op1[1],OP2_COL,&op2[1],COMMT_COL,comment,-1);
		remove_marker();
		scroll_to_row();
	}
	
	fclose(file);
	g_string_free(str,TRUE);
	gsim_update_statusbar(FILE_SBAR,filename);
}

void open_file_dialog_ok(GtkWidget *ok_button,gchar *file_on_command_line)
{
	const gchar *_name;
	if(file_on_command_line)
	{
		_name=file_on_command_line;
	}
	else
		//_name=gtk_file_selection_get_filename(GTK_FILE_SELECTION(open_file_dialog));
	    _name=gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (open_file_dialog));
	
	
	if(!g_file_test(_name,G_FILE_TEST_IS_REGULAR))  /*if not a file*/
		return;
	
	
	/*___________ check if file has valid signature ___________________*/
	struct gsim_signature sign;
	
	FILE *file;
	file=fopen(_name,"rb");
	if(!file)
	{
		g_printerr(_("Unable to open %s : ERROR : %s\n"),filename,strerror(errno));
		return;
	}
	
	/*check sign*/
	fread(&sign,sizeof(struct gsim_signature),1,file); 
	if(sign.lo!=0x55||sign.hi!=0xaa)
	{
		gtk_widget_hide(open_file_dialog);
		gsim_message(_("Not a valid GSim85 file."),GTK_MESSAGE_ERROR); 
		fclose(file);
		return;
	}
	/*_______________________________________________________________*/
	
	
	gsim_make_codeview_child(g_path_get_basename(_name)); /*make a page in notebook*/
	gtk_widget_show_all(codeview_notebook);
	gtk_notebook_set_current_page(GTK_NOTEBOOK( codeview_notebook ) ,0);
	
	if(!file_on_command_line)
	{
		gtk_widget_hide(open_file_dialog);
		while(gtk_events_pending())            /*make the page to switch*/
			gtk_main_iteration();
	}
	
	new_file=0;              /*not a newfile*/
	if_new_file=0;
	save_state=0;
	
	g_strlcpy(filename,g_path_get_basename(_name),50); /*filename*/
	absolute_filename=(gchar *)_name; /*update absolute filename*/
	_open_file();
}

void gsim_open_file(void)
{
	if(!open_file_dialog)     /*if it is the first time*/
	{
		/*open_file_dialog=gtk_file_selection_new(_("Open File ..."));
		g_signal_connect(GTK_FILE_SELECTION(open_file_dialog)->ok_button,"clicked",G_CALLBACK(open_file_dialog_ok),NULL);
		g_signal_connect(GTK_FILE_SELECTION(open_file_dialog)->cancel_button,"clicked",G_CALLBACK(close_file_selection),open_file_dialog);
		g_signal_connect(open_file_dialog,"delete-event",G_CALLBACK(delete_file_selection),NULL);*/
		
		open_file_dialog = gtk_file_chooser_dialog_new ("Open File ...",
				      GTK_WINDOW(gsim_appwindow),
				      GTK_FILE_CHOOSER_ACTION_OPEN,
				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
				      NULL); 
		
		/*filter_sim=gtk_file_filter_new();
		gtk_file_filter_set_name(filter_sim,"*.sim");
		gtk_file_filter_add_pattern(filter_sim,"*.sim");
		gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (open_file_dialog),filter_sim);*/
	}
	if (gtk_dialog_run (GTK_DIALOG (open_file_dialog)) == GTK_RESPONSE_ACCEPT)
  	{
    	open_file_dialog_ok(NULL,NULL);
    }

	gtk_widget_hide (open_file_dialog);
}


/*################ Save file as text ##############*/
static void _save_text_file(FILE *file)
{
	
	GString *str;
	str=g_string_new(NULL);
	
	GtkTreeIter iter;
	gboolean if_iter;
	for(if_iter=gtk_tree_model_get_iter_first(current_code_model,&iter);if_iter;
											if_iter=gtk_tree_model_iter_next(current_code_model,&iter))
	{
		gchar *address,*label,*mne,*op1,*op2,*comment;
		gtk_tree_model_get(current_code_model,&iter,ADDR_COL,&address,LABEL_COL,&label,MNE_COL,&mne,
										OP1_COL,&op1,OP2_COL,&op2,COMMT_COL,&comment,-1);
		if(!mne)
			mne=g_strdup("");       /*if a empty line(there is null mne so set it to x)*/
		
		g_string_truncate(str,0);   /*empty the string*/
		g_string_append_printf(str,"%s \t%s \t%s \t%s \t%s \t; %s\n",address,label,mne,op1,op2,comment); 
		fputs(str->str,file);

		g_free(address);
		g_free(label);
		g_free(mne);
		g_free(op1);
		g_free(op2);
		g_free(comment);
	}
	
	g_string_free(str,TRUE);
}

static void save_text_file_dialog_ok(void)
{
	const gchar *_name;
	
	//_name=gtk_file_selection_get_filename(GTK_FILE_SELECTION(save_text_file_dialog));
	_name=gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (save_text_file_dialog));
	if(g_file_test(_name,G_FILE_TEST_IS_DIR|G_FILE_TEST_IS_SYMLINK)||*_name=='\0') /*if not a file*/
		return;
	
	FILE *file;
	file=fopen(_name,"w");
	if(!file)
	{
		g_printerr(_("Unable to open %s : ERROR : %s\n"),filename,strerror(errno));
		return;
	}
	
	_save_text_file(file);
	fclose(file);
	gtk_widget_hide(save_text_file_dialog);                   /*hide selection dialog*/
}

void gsim_save_text_file(void)
{
	/*check file is not empty*/
	if(!if_have_iter())
		return;
	if(!save_text_file_dialog) /*if it is first time*/
	{
		/*save_text_file_dialog=gtk_file_selection_new(_("Save File As Text..."));
		g_signal_connect(GTK_FILE_SELECTION(save_text_file_dialog)->ok_button,"clicked",G_CALLBACK(save_text_file_dialog_ok),NULL);
		g_signal_connect(GTK_FILE_SELECTION(save_text_file_dialog)->cancel_button,"clicked",G_CALLBACK(close_file_selection),save_text_file_dialog);
		g_signal_connect(save_text_file_dialog,"delete-event",G_CALLBACK(delete_file_selection),NULL);*/
		
		save_text_file_dialog = gtk_file_chooser_dialog_new ("Save File As Text...",
				      GTK_WINDOW(gsim_appwindow),
				      GTK_FILE_CHOOSER_ACTION_SAVE,
				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
				      NULL);
		gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (save_text_file_dialog), TRUE);
	}
	
	if (gtk_dialog_run (GTK_DIALOG (save_text_file_dialog)) == GTK_RESPONSE_ACCEPT)
  	{
    	save_text_file_dialog_ok();
    }

	gtk_widget_hide (save_text_file_dialog);
}

/*#################### Print the file #####################*/
void gsim_print_file(void)
{
	/*check file is not empty*/
	if(!if_have_iter())
		return;
	
	FILE *file;
	static gint fd;
	GString *str;
	str=g_string_new("");
	g_string_append_printf(str,"/tmp/gsimtmp%d",fd);
	system("rm /tmp/gsimtmp*");
	file=fopen(str->str,"w");
	if(!file)
		return;
	_save_text_file(file);
	fclose(file);
	
	/*show somthing until find a printer*/
	GtkWidget *event_box,*label;
	event_box=gtk_window_new(GTK_WINDOW_POPUP);
	gtk_window_set_position(GTK_WINDOW(event_box),GTK_WIN_POS_CENTER);
	label=gtk_label_new(_("\n\n\tTrying to open printer ...\t\n\n"));
	gtk_container_add(GTK_CONTAINER(event_box),label);
	gtk_widget_show_all(event_box);
	while(gtk_events_pending())            /*make the page to switch*/
		gtk_main_iteration();
	
	g_string_prepend(str,"cat ");
	g_string_append(str,"| lpr");
	if(system(str->str))
	{
		gtk_widget_destroy(event_box);
		gsim_message(_("No printer found."),GTK_MESSAGE_ERROR);
	}
	else
	{
		gtk_widget_destroy(event_box);
		gsim_message(_("Request sent to printer."),GTK_MESSAGE_INFO);
	}
	g_string_free(str,TRUE);
	fd++;
}
